package io.jpress.module.article.flowable.listener;

import com.github.houbb.heaven.util.lang.StringUtil;
import com.jfinal.aop.Inject;
import io.jboot.utils.StrUtil;
import io.jpress.commons.flowable.FlowConsts;
import io.jpress.core.flowable.AutoLoadEventListener;
import io.jpress.core.flowable.FlowableUtil;
import io.jpress.module.article.flowable.ArticleFlowConsts;
import io.jpress.module.article.model.Article;
import io.jpress.module.article.model.ArticleFlowStatus;
import io.jpress.module.article.service.ArticleFlowStatusService;
import io.jpress.module.article.service.ArticleService;
import org.flowable.bpmn.model.ExtensionAttribute;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.UserTask;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.common.engine.api.delegate.event.FlowableEntityEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl;

import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 监听器作用：当作者修改了文章后，进入待办任务，点击完成按钮时，需要把任务实例的 action 值设置为 unknow。
 */
@AutoLoadEventListener(types = FlowableEngineEventType.TASK_COMPLETED)
public class ArticleTaskCompletedListener implements FlowableEventListener {

    @Inject
    private ArticleFlowStatusService articleFlowStatusService;

    @Inject
    private ArticleService articleService;

    @Override
    public void onEvent(FlowableEvent event) {

        if (!(event instanceof FlowableEntityEvent)) {
            return;
        }

        Object entityOriginal = ((FlowableEntityEvent) event).getEntity();


        if (!(entityOriginal instanceof TaskEntityImpl)) {
            return;
        }

        TaskEntityImpl entity = (TaskEntityImpl) entityOriginal;

        //非文章类的流程
        if (!ArticleFlowConsts.ARTICLE_CONTENT_TYPE.equals(entity.getVariable(FlowConsts.VAR_CONTENT_TYPE))) {
            return;
        }


        Object articleId = entity.getVariable(FlowConsts.VAR_CONTENT_ID);
        Article article = articleService.findById(articleId);


        String comment = (String) entity.getVariable(FlowConsts.VAR_COMMENT);
        if (StringUtil.isNotBlank(comment)) {
            article.putOption("lastFlowComment", comment);
            articleService.update(article);
        }


        //总实例数量
        Integer nrOfInstances = (Integer) entity.getVariable("nrOfInstances");

        //非多实例，需要设置文章当前的流程状态
        if (nrOfInstances == null || nrOfInstances == 0) {
            ArticleFlowStatus flowStatus = articleFlowStatusService.findByProcessInstanceId(entity.getProcessInstanceId());
            String action = (String) entity.getVariable(FlowConsts.VAR_ACTION);
            if (FlowConsts.ACTION_STATUS_REFUSE.equals(action)) {
                flowStatus.setStatus(ArticleFlowStatus.STATUS_REFUSE);
                articleFlowStatusService.update(flowStatus);
            } else if (FlowConsts.ACTION_STATUS_AGREE.equals(action)) {
                flowStatus.setStatus(ArticleFlowStatus.STATUS_AGREE);
                articleFlowStatusService.update(flowStatus);
            } else if (FlowConsts.ACTION_STATUS_REBUT.equals(action)) {
                flowStatus.setStatus(ArticleFlowStatus.STATUS_REBUT);
                articleFlowStatusService.update(flowStatus);
            }
        }
        //会签逻辑：需要执行同意条件
        else {

            //当前任务未执行完毕，得到 nrOfCompletedInstances 的值不包含当前任务
            Map<String, Object> variables = entity.getVariables();
            if (variables.containsKey("nrOfCompletedInstances")) {
                Integer nrOfCompletedInstances = (Integer) variables.get("nrOfCompletedInstances");
                variables.put("nrOfCompletedInstances", nrOfCompletedInstances + 1);
            }

            FlowElement flowElement = FlowableUtil.getFlowElementByDefKey(entity.getProcessDefinitionId(), entity.getTaskDefinitionKey());

            UserTask userTask = (UserTask) flowElement;


            //是否是多实例中，最后一个执行的实例
            boolean isLastTaskInMultiInstance = false;

            String completionConditionExpression = userTask.getLoopCharacteristics().getCompletionCondition();
            if (StrUtil.isNotBlank(completionConditionExpression)) {
                Object expressionResult = FlowableUtil.execExpression(completionConditionExpression, variables);
                isLastTaskInMultiInstance = "true".equalsIgnoreCase(String.valueOf(expressionResult).trim());
            } else {
                //当前的循环 index
                Integer loopCounter = (Integer) variables.get("loopCounter");

                if (Objects.equals(nrOfInstances, loopCounter)) {
                    isLastTaskInMultiInstance = true;
                }
            }


            if (isLastTaskInMultiInstance) {
                String agreeExpression = null;
                Map<String, List<ExtensionAttribute>> attributes = flowElement.getAttributes();
                if (attributes != null) {
                    List<ExtensionAttribute> agreeCondition = attributes.get("agreeCondition");
                    if (agreeCondition != null && !agreeCondition.isEmpty()) {
                        agreeExpression = agreeCondition.get(0).getValue();
                    }
                }

                boolean agreeInMultiInstanceUserTask = false;

                //用户填写了同意的条件，根据同意条件来判断
                if (StrUtil.isNotBlank(agreeExpression)) {
                    Object expressionResult = FlowableUtil.execExpression(agreeExpression, variables);
                    agreeInMultiInstanceUserTask = "true".equalsIgnoreCase(String.valueOf(expressionResult).trim());
                }

                //用户未填写同意条件，默认：少数服从多数
                else {
                    Long agreeCount = getLongVariable(variables, FlowConsts.VAR_ACTION_AGREE_COUNT);
                    Long rebutCount = getLongVariable(variables, FlowConsts.VAR_ACTION_REBUT_COUNT);
                    Long refuseCount = getLongVariable(variables, FlowConsts.VAR_ACTION_REFUSE_COUNT);
                    agreeInMultiInstanceUserTask = agreeCount > (refuseCount + rebutCount);
                }

                // 同意发布，往下一步走（也有可能走到完成节点）
                if (agreeInMultiInstanceUserTask) {
                    FlowableUtil.getRuntimeService().setVariable(entity.getExecutionId(), FlowConsts.VAR_ACTION, FlowConsts.ACTION_STATUS_AGREE);
                }

                // 拒绝发布，直接停止流程
                else {
                    FlowableUtil.getRuntimeService().setVariable(entity.getExecutionId(), FlowConsts.VAR_ACTION, FlowConsts.ACTION_STATUS_AGREE);
                    FlowableUtil.stopProcessInstance(entity.getProcessInstanceId(), variables);
                }
            }
        }

    }

    private Long getLongVariable(Map<String, Object> variables, String variableName) {
        Number oldCount = (Number) variables.getOrDefault(variableName, 0L);
        return oldCount.longValue();
    }


    @Override
    public boolean isFailOnException() {
        return false;
    }

    @Override
    public boolean isFireOnTransactionLifecycleEvent() {
        return false;
    }

    @Override
    public String getOnTransaction() {
        return null;
    }
}
